#ifndef MESHHEADER
#define MESHHEADER

#include "GE_Base.h"

namespace Syp
{
///IndexBlock describes a draw call to draw part(s) of a mesh. Each Material will have a corresponding Index Block in the mesh. This is because different polygons with different materials require seperate draw calls. Thus the existence of IndexBlocks which seperates polygons based on material.
struct IndexBlock
{
	///The SubMaterial ID in the current Material effect.Used in NIndexedMesh as well.
	PInt materialID;
	///Smallest value of index in this block.
	PShort smallest;
	///Largest value of index in block.
	PShort largest;
	///Number of indices in this block. Used in NIndexedMesh as well.
	PShort count;
	///offset in index Buffer. Used in NIndexedMesh as well.
	PShort offset;
};

/*
	AnimSet describes the start and end times of a particular animation
*/
struct AnimSet
{
	String name;
	float start;
	float end;
};

///BaseMesh is an Abstract Base Class which defines common properties required by all meshes. As of version 0.12, all Meshes are managed. However user is given full control over when the garbage collector runs. Garbage collector will not be called without the user calling it.
class SYPAPI BaseMesh : public Resource
{
	///Renderer is a friend because it needs info of the mesh to render/transform it for Rendering. 
	friend class Renderer;
public:
	BaseMesh(const String& filename);	
	///Draws the Mesh
	virtual void draw() = 0;
	///Sends mesh contents to the gfx card. Any changes to the mesh after addMesh()		will not be reflected unless updateMesh() is called. Usually static meshes should	only call this function should there be changes update. Dynamic meshes are		automatically updated every frame regardless of change.
	virtual void updateMesh() = 0;
	///Mesh does it's stuff it needs to do every frame. For example animate itself based on a MeshInstance's current frame time.
	//virtual void update(MeshInstance* m) = 0;
	virtual void removeFromVRAM() = 0;

	void setVertexType(VertexType vt);
	///calculate stride
	void calcStride();	
	///Returns the number of drawCalls used by this mesh
	PInt getNumDrawCalls();	
	///Returns the VertexFormat of the Mesh.
	VertexType getVertType();
	///Returns a reference to a drawcall
	IndexBlock& getDrawCall(PInt index);
	///Set the type of primitives to use for drawing mesh, (Triangles/tri-strip)
	void setRenderingFormat(RenderingFormat rf);
	///Returns the number of vertices in mesh.
	PInt getNumVertices();
	///Returns the default material filename for this mesh
	const String& getMaterialName();
	///Sets the bounding radius of the model which is used during frustum culling calculations.If 0, model is always drawn.
	void setBoundingRadius(float radius);
	///Returns the current bounding radius of the model.
	float getBoundingRadius();
	///Pushes back an index block into the mesh
	void pushBackIndexBlock(IndexBlock& ib);
	///Inserts an array of floats into the mesh's Data array
	void insertIntoData(float* dat, int count, int pos=0);


	///Returns a reference to the vector containing the drawCalls.Use with caution.
	std::vector<IndexBlock>& getDrawCallsRef();

	///Reurns a reference to the number of vertices variable. Use with caution.
	PInt& getNumVerticesRef();

	///Returns a reference to the data vector.Use with caution.
	FloatArray& getDataRef();
	///Defines the default material for mesh. MeshInstances using this mesh will by default also use the default material.
	void setDefaultMaterial(const String& mat);
protected:
	virtual ~BaseMesh();
	///NOT FOR CLIENT USE adds an instance to its list. This method is unsafe to be called by the user. Use MeshInstance.useMesh()/clearMesh() instead.
	friend void MeshInstance::useMesh(BaseMesh* m);
	friend void MeshInstance::clearMesh();	
	///Reference info
	//std::list<MeshInstance*> instances;
	///Static/Dynamic model
	ModelType type;	
	///Number of Vertices
	PInt numOfVertices;	
	///Type of Vertex format, private because we need to recalculate stride upon change.
	VertexType vertType;
	///VertexDATA/Normal/UV/etc..
	FloatArray data;	
	///Has the properties of the submeshes which require diff draw calls. 
	std::vector<IndexBlock> drawCalls;	
	
private:
    float modelRadius;	
	///ID generated by GL for VBOs
	PInt dataID;
	///Triangles,strip,watever
	RenderingFormat format;

	///The default material for this mesh. We use a String bcos we don't want to help the user to load it, incase the user calls the GC after loading the mesh, the MeshInstance will crash if it used the pointer.
	String material;

    ///size of stride
	int stride;
	
};
}

#endif

